home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 June / Macworld (1999-06).dmg / Shareware World / Info / For Developers / MacZoop2.0.sea / MacZoop2.0 / Required Classes / ZWindowManager.cpp < prev    next >
Text File  |  1999-02-24  |  41KB  |  1,693 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"             
  5. *
  6. *
  7. *
  8. *            ZWindowManager.cpp        -- desktop class handles floaters
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "MacZoop.h"
  23. #include    "ZWindow.h"
  24. #include    "ZDialog.h"
  25. #include    "ZEventHandler.h"
  26. #include    "ProjectSettings.h"
  27.  
  28. #if _USE_DIR_POPUP
  29. #include    "DirectoryPopup.h"
  30. #include    "FinderObjects.h"
  31. #endif
  32.  
  33. #if _WPOS_WINDOW_PLACEMENT
  34. #include    "ZResourceFile.h"
  35. #endif
  36.  
  37. #include    <dialogs.h>
  38.  
  39.  
  40. ZWindowManager*        gWindowManager = NULL;
  41.  
  42.  
  43. /*--------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  44.  
  45. ZWindowManager::ZWindowManager()
  46.     : ZComrade()
  47. {
  48.     // make the lists
  49.     
  50.     FailNIL( nonFloaters = new ZWindowList());
  51.     FailNIL( floaters = new ZWindowList());
  52.     
  53.     wmWindows = NULL;
  54.     wmMenu = NULL;
  55.     wmItemOffset = 0;
  56.     wmActive = TRUE;
  57.     wmDDDeactivated = FALSE;
  58.     
  59.     SetRect( &fStoredZoom, 0, 0, 0, 0 );
  60.     fStoredZoomSource = fStoredZoom;
  61.     
  62.     // set up member for controlling window placement
  63.     
  64.     globalPlaceLoc.h = 2;
  65.     globalPlaceLoc.v = GetMBarHeight() + 2;
  66.     
  67.     // we are the only one, and we are global
  68.     
  69.     gWindowManager = this;
  70. }
  71.  
  72. /*---------------------------------***  DESTRUCTOR  ***---------------------------------*/
  73.  
  74.  
  75. ZWindowManager::~ZWindowManager()
  76. {
  77.     if ( nonFloaters )
  78.     {
  79.         nonFloaters->DisposeAll();
  80.         ForgetObject( nonFloaters );
  81.     }
  82.         
  83.     if ( floaters )
  84.     {
  85.         floaters->DisposeAll();
  86.         ForgetObject( floaters );
  87.     }
  88.         
  89.     if ( wmWindows )
  90.         ForgetObject( wmWindows );
  91. }
  92.  
  93.  
  94. /*---------------------------------***  ADDWINDOW  ***----------------------------------*/
  95. /*    
  96. add the window to the relevant list of windows, and set its initial (Z) position
  97. ----------------------------------------------------------------------------------------*/
  98.  
  99. void    ZWindowManager::AddWindow( ZWindow* aWindow )
  100. {
  101.     FailNILParam( aWindow );
  102.     
  103.     ZWindow*    zw = GetBottomFloater();
  104.     
  105.     // determine if this window is a floater or not:
  106.     
  107.     if ( aWindow->Floats())
  108.     {
  109.         BringBehind( aWindow, zw );
  110.         floaters->AppendItem( aWindow );
  111.     }
  112.     else
  113.     {
  114.         Boolean        eligibleWindow;
  115.         
  116.         eligibleWindow = ( ! IsDialog( aWindow )) ||
  117.                             ( IsDialog( aWindow ) && ! ((ZDialog*) aWindow )->IsModal());
  118.         
  119.         // move behind the bottom floater unless this is a modal dialog
  120.  
  121.         if ( eligibleWindow )
  122.             BringBehind( aWindow, zw );
  123.         
  124.         nonFloaters->AppendItem( aWindow );
  125.         
  126.         // if we're maintaining a "Windows" menu, append the window to our list if
  127.         // it non-floating and not a modal dialog box.
  128.         
  129.         if ( wmWindows && eligibleWindow )
  130.             wmWindows->AppendItem( aWindow );
  131.             
  132.         BuildWindowsMenu();
  133.     }    
  134.     
  135.     SendMessage( kWMMsgWindowAdded, aWindow );
  136. }
  137.  
  138.  
  139. /*--------------------------------***  REMOVEWINDOW  ***--------------------------------*/
  140. /*
  141. remove the window from the relevant list; make sure the next window is activated correctly.    
  142. ----------------------------------------------------------------------------------------*/
  143.  
  144. void    ZWindowManager::RemoveWindow( ZWindow* aWindow )
  145. {
  146.     FailNILParam( aWindow );
  147.     
  148.     aWindow->Hide();
  149.     
  150.     if ( aWindow->Floats())
  151.         floaters->DeleteObject( aWindow );
  152.     else
  153.     {
  154.         nonFloaters->DeleteObject( aWindow );
  155.         
  156.         if ( wmWindows )
  157.             wmWindows->DeleteObject( aWindow );
  158.         
  159.         // if all windows closed, reset global positioning variable
  160.         
  161.         if ( CountWindows() == 0 )
  162.         {
  163.             globalPlaceLoc.h = 2;
  164.             globalPlaceLoc.v = GetMBarHeight() + 2;
  165.         }
  166.     }
  167.     
  168.     SendMessage( kWMMsgWindowRemoved, aWindow );
  169. }
  170.  
  171.  
  172. /*-------------------------------***  INITIALLYPLACE  ***-------------------------------*/
  173. /*
  174. Call this after creating a window to place it initially. By default, this will stack the
  175. windows from top left towards bottom right, taking into account their correct title bar
  176. heights, etc. Override for other behaviours. Floating windows are ignored by this method.    
  177. ----------------------------------------------------------------------------------------*/
  178.  
  179. void    ZWindowManager::InitiallyPlace( ZWindow* aWindow )
  180. {
  181.     Rect    wBorder;
  182.     short    gh, gv;
  183.     
  184.     FailNILParam( aWindow );
  185.     
  186.     if ( ! aWindow->Floats())
  187.     {
  188.         aWindow->GetStructureFrameBorder( &wBorder );
  189.         
  190.         gh = globalPlaceLoc.h + wBorder.left;
  191.         gv = globalPlaceLoc.v + wBorder.top;
  192.         
  193.         aWindow->PlaceAt( gh, gv );
  194.         
  195.         globalPlaceLoc.h += wBorder.left + 2;
  196.         globalPlaceLoc.v += wBorder.top + 2;
  197.         
  198.         // if the bottom of the window falls off the screen, make it a bit less
  199.         // tall so that all its frame is visible.
  200.         
  201.         RgnHandle    wStruct;
  202.         short        overHang;
  203.         GDHandle    mainDev;
  204.         
  205.         mainDev = GetMainDevice();
  206.         aWindow->GetStructureRegion( wStruct = NewRgn());
  207.         
  208.         overHang = (*mainDev)->gdRect.bottom - (*wStruct)->rgnBBox.bottom;
  209.         
  210.         // if overhang is negative, we've gone too far, so make the window smaller.
  211.         
  212.         if ( overHang < 0 )
  213.         {
  214.             // only resize the window if it's a naturally resizable type, otherwise
  215.             // the user may end up with an unexpectedly nasty-looking window.
  216.             
  217.             WindowPtr    macWindow = aWindow->GetMacWindow();
  218.             short        wType;
  219.             
  220.             wType = GetWVariant( macWindow );
  221.  
  222.             if ( wType == documentProc  ||
  223.                  wType == zoomDocProc )
  224.             {
  225.                 wBorder = macWindow->portRect;
  226.             
  227.                 wBorder.bottom += overHang;
  228.                 aWindow->SetSize( wBorder.right - wBorder.left, wBorder.bottom - wBorder.top - 2, FALSE );
  229.             }
  230.             
  231.             // in any case the next window placed had better start back at the top...
  232.             
  233.             globalPlaceLoc.v = GetMBarHeight() + 2;
  234.             globalPlaceLoc.h += 10;
  235.         }
  236.         
  237.         DisposeRgn( wStruct );
  238.     }
  239. }
  240.  
  241.  
  242. /*---------------------------------***  HIDEWINDOW  ***---------------------------------*/
  243. /*    
  244. make the window invisible to the user. Does not change its front-to-back ordering unless
  245. it was the top one in its layer, in which case the one below it is selected.
  246. ----------------------------------------------------------------------------------------*/
  247.  
  248. void    ZWindowManager::HideWindow( ZWindow* aWindow )
  249. {
  250.     FailNILParam( aWindow );
  251.     
  252.     WindowPtr    w = aWindow->GetMacWindow();
  253.     short        i;
  254.     
  255.     if ( w != NULL )
  256.     {
  257.         ShowHide( w, FALSE );
  258.         HiliteWindow( w, FALSE );
  259.         
  260.         SendMessage( kWMMsgWindowHidden, aWindow );
  261.     }
  262.     // if this was the top window, select the next non-hidden one
  263.     
  264.     if ( aWindow->Floats())
  265.     {
  266.         if ( aWindow == GetTopFloater() &&
  267.              floaters->CountItems() > 1 )
  268.         {
  269.             for( i = 2; i <= floaters->CountItems(); i++ )
  270.             {
  271.                 aWindow = (ZWindow*) floaters->GetObject( i );
  272.             
  273.                 if ( aWindow && aWindow->IsVisible())
  274.                 {
  275.                     SelectWindow( aWindow );
  276.                     break;
  277.                 }
  278.             }
  279.         }
  280.     }
  281.     else
  282.     {
  283.         if ( aWindow == GetTopWindow())
  284.         {
  285.             if ( nonFloaters->CountItems() > 1 )
  286.             {
  287.                 for( i = 2; i <= nonFloaters->CountItems(); i++ )
  288.                 {
  289.                     aWindow = (ZWindow*) nonFloaters->GetObject( i );
  290.                 
  291.                     if ( aWindow && aWindow->IsVisible())
  292.                     {
  293.                         SelectWindow( aWindow );
  294.                         break;
  295.                     }
  296.                 }
  297.             }
  298.             else
  299.             {
  300.                 // the window being hidden is the only one. If a dialog,
  301.                 // activate the floaters
  302.                 
  303.                 if ( IsDialog( aWindow ))
  304.                     Activate();
  305.             }
  306.         }
  307.     }
  308. }
  309.  
  310.  
  311. /*---------------------------------***  SHOWWINDOW  ***---------------------------------*/
  312. /*    
  313. make the window visible to the user. Does not change its front-to-back ordering
  314. ----------------------------------------------------------------------------------------*/
  315.  
  316. void    ZWindowManager::ShowWindow( ZWindow* aWindow )
  317. {
  318.     FailNILParam( aWindow );
  319.     
  320.     if ( ! aWindow->IsVisible())
  321.     {
  322.         #if _ZOOM_RECT_FX
  323.         
  324.         if ( gMacInfo.hasDragManager )
  325.         {
  326.             RgnHandle    wStruct;
  327.         
  328.             aWindow->GetStructureRegion( wStruct = NewRgn());
  329.             aWindow->zoomSource = gZoomFXSourceRect;
  330.             
  331.             ZoomRects( &gZoomFXSourceRect, &(*wStruct)->rgnBBox, 10, kZoomAccelerate );
  332.             DisposeRgn( wStruct );
  333.         }
  334.         #endif
  335.         
  336.         ShowHide( aWindow->GetMacWindow(), TRUE );
  337.         SendMessage( kWMMsgWindowShown, aWindow );
  338.     
  339.         if ( aWindow == GetTopWindow() ||
  340.              aWindow == GetTopFloater())
  341.             SelectWindow( aWindow );
  342.     }
  343. }
  344.  
  345.  
  346. /*--------------------------------***  SELECTWINDOW  ***--------------------------------*/
  347. /*    
  348. make the window active. This handles the front-to-back ordering and creates the "floating"
  349. window illusion.
  350. ----------------------------------------------------------------------------------------*/
  351.  
  352. void    ZWindowManager::SelectWindow( ZWindow* aWindow )
  353. {
  354.     FailNILParam( aWindow );
  355.     
  356.     // this is where a certain amount of cunning comes in. To "Select" a non-floater, it
  357.     // is actually moved to come behind the bottom floater. Floaters are treated normally.
  358.     // Dialogs can come in front of all windows, though they will be set to non-floating.
  359.     
  360.     ZWindow*    zw;
  361.     long        i;
  362.     
  363.     if (! aWindow->IsVisible())
  364.     {
  365.         // if window hitherto has not been seen by the user, and the setting indicates we
  366.         // want the effect, perform the zoom open animation
  367.         
  368.         #if _ZOOM_RECT_FX
  369.         
  370.         if ( gMacInfo.hasDragManager )
  371.         {
  372.             RgnHandle    wStruct;
  373.         
  374.             aWindow->GetStructureRegion( wStruct = NewRgn());
  375.             aWindow->zoomSource = gZoomFXSourceRect;
  376.             
  377.             ZoomRects( &gZoomFXSourceRect, &(*wStruct)->rgnBBox, 10, kZoomAccelerate );
  378.             DisposeRgn( wStruct );
  379.         }
  380.         #endif
  381.     }    
  382.     // manipulate our lists and the mac window list
  383.     
  384.     if ( aWindow->Floats())
  385.     {
  386.         i = floaters->FindIndex( aWindow );
  387.         
  388.         // move to head of list, if not there already
  389.         
  390.         if ( i > 1 )
  391.         {
  392.             // deactivate current "top"
  393.             
  394.             zw = GetTopFloater();
  395.             
  396.             if ( zw )
  397.             {
  398.                 #if _ALL_FLOATERS_ACTIVE == OFF
  399.                 HiliteWindow( zw->GetMacWindow(), FALSE );
  400.                 #endif
  401.                 
  402.                 zw->Deactivate();
  403.                 SendMessage( kWMMsgFloaterDeactivated, zw );
  404.             }
  405.             
  406.             floaters->MoveToFront( i );
  407.             BringBehind( aWindow, NULL );
  408.         }    
  409.         // hilite and activate the new "top" window
  410.         // if window is not visible, make it so
  411.     
  412.         ShowHide( aWindow->GetMacWindow(), TRUE );
  413.         aWindow->Activate();
  414.         HiliteWindow( aWindow->GetMacWindow(), TRUE );
  415.         SendMessage( kWMMsgFloaterActivated, aWindow );
  416.     }
  417.     else
  418.     {
  419.         i = nonFloaters->FindIndex( aWindow );
  420.         
  421.         // if already on top, do nothing
  422.         
  423.         if ( i > 1 )
  424.         {
  425.             // deactivate the current "top"
  426.             
  427.             zw = GetTopWindow();
  428.             
  429.             if ( zw )
  430.                 PostActivation( zw, FALSE );
  431.             
  432.             // move to head of list
  433.             
  434.             nonFloaters->MoveToFront( i );
  435.         }    
  436.         
  437.         // bring window behind the bottom floater, unless it's a dialog, in which
  438.         // case it's put on top of everything
  439.  
  440.         if ( IsDialog( aWindow ))
  441.         {
  442.             if ( wmActive )
  443.                 Deactivate();
  444.             
  445.             BringBehind( aWindow, NULL );
  446.         }
  447.         else
  448.         {
  449.             zw = GetBottomFloater();
  450.             BringBehind( aWindow, zw );
  451.             
  452.             if ( ! wmActive )
  453.                 Activate();
  454.         }
  455.         
  456.         // hilite and activate the new "top" window
  457.         // if window is not visible, make it so
  458.     
  459.         ShowHide( aWindow->GetMacWindow(), TRUE );
  460.         
  461.         if ( ! aWindow->IsActive())
  462.             PostActivation( aWindow, TRUE );
  463.     }
  464. }
  465.  
  466.  
  467. /*-----------------------------***  DRAGWINDOWOUTLINE  ***------------------------------*/
  468. /*    
  469. drag the outline of the window and move it when the mouse is released. This replaces the
  470. toolbox routine DragWindow, and in addition does a nicer job of clipping the outline.
  471. ----------------------------------------------------------------------------------------*/
  472.  
  473. void    ZWindowManager::DragWindowOutline( ZWindow* aWindow, Point startPt, const short modifiers )
  474. {
  475.     FailNILParam( aWindow );
  476.     
  477.     // replaces the toolbox DragWindow, because that will bring a window to the front if
  478.     // you let it.
  479.     
  480.     WindowPtr    w;
  481.     RgnHandle    dragRgn, temp = NULL;
  482.     Rect        limitRect;
  483.     long        dragOffset;
  484.     GrafPort    screenPort;
  485.     GrafPtr        savePort;
  486.     Point        wPosition;
  487.     
  488.     w = aWindow->GetMacWindow();
  489.     PauseCursorAnimation( 0 );
  490.     
  491.     // if window frontmost and command key down, call command-click hook and return. The hook
  492.     // can be overridden to implement stuff such as popping up a directory path menu, etc.
  493.     
  494.     if ( aWindow == GetTopWindow() &&
  495.          ( modifiers & cmdKey ) == cmdKey )
  496.     {
  497.         // the hook returns a boolean to indicate whether processing should continue or not.
  498.         // If FALSE, we continue, otherwise we abort. The default hook method just returns FALSE
  499.         
  500.         if ( CommandClickInFrontDragBar( aWindow, startPt ))
  501.             return;
  502.     }
  503.     
  504.     // select the window if command key not down
  505.     
  506.     #if _DRAGWINDOW_COMPATIBLE == OFF
  507.     
  508.     if (( modifiers & cmdKey ) == 0 &&
  509.         aWindow != GetTopWindow() &&
  510.         aWindow != GetTopFloater())
  511.     {
  512.         SelectWindow( aWindow );
  513.     }
  514.     #if _UPDATE_ON_SELECT
  515.     
  516.     aWindow->PerformUpdate();
  517.     
  518.     #endif
  519.     
  520.     #endif
  521.     
  522.     // get the limit rect
  523.     
  524.     limitRect = (*GetGrayRgn())->rgnBBox;
  525.     InsetRect( &limitRect, 4, 4 );
  526.     
  527.     // get the outline to drag. This is simply a copy of the window's structure region
  528.     
  529.     FailNIL( dragRgn = NewRgn());
  530.     
  531.     CopyRgn(((WindowPeek) w)->strucRgn, dragRgn );
  532.     
  533.     // set up a port in which to drag the outline. We do this to be good citizens,
  534.     // since meddling with the Mac's Window Manager port is tricky to get away with.
  535.     
  536.     GetPort( &savePort );
  537.     OpenPort( &screenPort );
  538.     SetPort( &screenPort );
  539.     
  540.     // make sure we can drag on the whole desktop
  541.     
  542.     screenPort.portRect = (*GetGrayRgn())->rgnBBox;
  543.     SetClip( GetGrayRgn());
  544.     CopyRgn( screenPort.clipRgn, screenPort.visRgn );
  545.     
  546.     // Remove the regions of all windows in front from the clip region, so it is clearer
  547.     // what will happen when the window moves.
  548.     
  549.     FailNIL( temp = NewRgn());
  550.     CalcWindowRgns( aWindow, temp );
  551.     DiffRgn( screenPort.clipRgn, temp, screenPort.clipRgn );
  552.     
  553.     // if we have system 8.0 or later, use a 2-pixel gray drag region, not a 1-pixel
  554.     
  555.     if ( gMacInfo.systemVersion >= 0x0800 )
  556.     {
  557.         CopyRgn( dragRgn, gUtilRgn );
  558.         InsetRgn( gUtilRgn, 2, 2 );
  559.         DiffRgn( dragRgn, gUtilRgn, dragRgn );
  560.     }
  561.     
  562.     // the mouse may have moved away from the startPt already, since the update may have taken
  563.     // a while. In order to prevent the window jumping in this situation, we just check that the
  564.     // mouse is still in fact, down!
  565.     
  566.     if ( StillDown())
  567.         dragOffset = DragGrayRgn( dragRgn, startPt, &limitRect, &limitRect, noConstraint, NULL );
  568.     else
  569.         dragOffset = kMouseUpOutOfSlop;
  570.         
  571.     // delete our port
  572.     
  573.     ClosePort( &screenPort );
  574.     SetPort( savePort );
  575.     
  576.     // check the window drag wasn't bogus:
  577.     
  578.     if ( dragOffset != kMouseUpOutOfSlop )
  579.     {
  580.         // OK, figure out where the window moved to, and move it there. If the command key
  581.         // is not down, select tha' booga!
  582.         
  583.         SetPort( w );
  584.         
  585.         wPosition = topLeft( w->portRect );
  586.         LocalToGlobal( &wPosition );
  587.         SetPort( savePort );
  588.         
  589.         // if we are exactly compatible with toolbox DragWindow(), then select the window here
  590.         
  591.         #if _DRAGWINDOW_COMPATIBLE
  592.         
  593.         if (( modifiers & cmdKey ) == 0 &&
  594.             aWindow != GetTopWindow() &&
  595.             aWindow != GetTopFloater())
  596.             SelectWindow( aWindow );
  597.         
  598.         #endif
  599.         
  600.         MoveWindow( w, wPosition.h + LoWord( dragOffset ), wPosition.v + HiWord( dragOffset ), FALSE );
  601.         SendMessage( kWMMsgWindowMoved, aWindow );
  602.     }    
  603.     // clean up
  604.     
  605.     DisposeRgn( dragRgn );
  606.     
  607.     if ( temp )    
  608.         DisposeRgn( temp );
  609.         
  610.     ResumeCursorAnimation();
  611. }
  612.  
  613.  
  614. /*-----------------------------------***  SUSPEND  ***----------------------------------*/
  615. /*    
  616. application is suspending- hide the floaters
  617. ----------------------------------------------------------------------------------------*/
  618.  
  619. void    ZWindowManager::Suspend()
  620. {
  621.     // the application is being suspended, so all floaters should be hidden
  622.     
  623.     ZWindow        *aFloater, *tw;
  624.     short        i;
  625.     
  626.     for (i = 1; i <= floaters->CountItems(); i++)
  627.     {
  628.         aFloater = (ZWindow*) floaters->GetObject( i );
  629.         
  630.         if ( aFloater )
  631.             ShowHideFloater( aFloater, TRUE );
  632.     }
  633.     
  634.     tw = GetTopWindow();
  635.     
  636.     if ( tw )
  637.         PostActivation( tw, FALSE );
  638. }
  639.  
  640. /*-----------------------------------***  RESUME  ***-----------------------------------*/
  641. /*    
  642. application is resuming- show the floaters
  643. ----------------------------------------------------------------------------------------*/
  644.  
  645. void    ZWindowManager::Resume()
  646. {
  647.     // the application is being resumed, so all floaters should be re-shown.
  648.     
  649.     ZWindow        *aFloater, *tw;
  650.     short        i;
  651.     
  652.     for (i = 1; i <= floaters->CountItems(); i++)
  653.     {
  654.         aFloater = (ZWindow*) floaters->GetObject( i );
  655.         
  656.         if ( aFloater )
  657.             ShowHideFloater( aFloater, FALSE );
  658.     }
  659.  
  660.     tw = GetTopWindow();
  661.     
  662.     if ( tw )
  663.         PostActivation( tw, TRUE );
  664. }
  665.  
  666. /*---------------------------------***  DEACTIVATE  ***---------------------------------*/
  667. /*    
  668. a modal dialog is coming up, so deactivate all floaters. This is called for you when
  669. necessary. If you are displaying a non-MacZoop dialog (Standard File, etc) you should
  670. use DeactivateForDialog() instead.
  671. ----------------------------------------------------------------------------------------*/
  672.  
  673. void    ZWindowManager::Deactivate()
  674. {
  675.     // a dialog is up, so all floaters plus the top window must be deactivated
  676.     
  677.     ZWindow*    zw;
  678.     
  679. #if _ALL_FLOATERS_ACTIVE == OFF
  680.     
  681.     zw = GetTopFloater();
  682.     
  683.     if ( zw )
  684.         PostActivation( zw, FALSE );
  685.         
  686. #else
  687.     
  688.     short    i;
  689.     
  690.     for (i = 1; i <= floaters->CountItems(); i++ )
  691.     {
  692.         zw = (ZWindow*) floaters->GetObject( i );
  693.     
  694.         if ( zw )
  695.             PostActivation( zw, FALSE );
  696.     }
  697.     
  698. #endif
  699.  
  700.     wmActive = FALSE;
  701. }
  702.  
  703.  
  704. /*----------------------------***  DEACTIVATEFORDIALOG  ***-----------------------------*/
  705. /*    
  706. in order to support nice zoom rects when non-MacZoop dialogs are displayed, this method
  707. can be called instead of Deactivate to provide the animation by proxy for the dialog.
  708. This should ONLY be called for dialogs and alerts that are not ZDialog objects.
  709. ----------------------------------------------------------------------------------------*/
  710.  
  711. void    ZWindowManager::DeactivateForDialog( short dlogID, Boolean isAlert  )
  712. {
  713.     ZWindow*    zw;
  714.     
  715.     Deactivate();
  716.     
  717.     zw = GetTopWindow();
  718.     
  719.     if ( zw )
  720.     {
  721.         PostActivation( zw, FALSE );
  722.         wmDDDeactivated = TRUE;
  723.         
  724.         zw->PerformUpdate();
  725.     }
  726.     
  727.     SendMessage( kWMMsgMacDialogUp, NULL );
  728.     
  729.     #if _ZOOM_RECT_FX
  730.     
  731.     // in order to display the animation by proxy for the dialog we are about to put
  732.     // up, we need to obtain the dialog's window frame by taking a peek into the
  733.     // dialog record
  734.     
  735.     if ( gMacInfo.hasDragManager && ( dlogID != -1 ))
  736.     {
  737.         Rect            r;
  738.         AlertTHndl        atH;
  739.         DialogTHndl        dtH;
  740.         
  741.         if ( isAlert )
  742.         {
  743.             atH = (AlertTHndl) GetResource( 'ALRT', dlogID );
  744.         
  745.             if ( atH )
  746.             {
  747.                 r = (*atH)->boundsRect;
  748.                 ReleaseResource((Handle) atH );
  749.             }
  750.         }
  751.         else
  752.         {    
  753.             dtH = (DialogTHndl) GetResource( 'DLOG', dlogID );
  754.             
  755.             if ( dtH )
  756.             {
  757.                 r = (*dtH)->boundsRect;
  758.                 ReleaseResource((Handle) dtH );
  759.             }    
  760.         }
  761.         
  762.         // we are going to need to assume that the dialog/alert is going to be placed on the screen
  763.         // in the standard alert position (for now- there are ways to be more intelligent about this)
  764.         // so we have to compute that location:
  765.         
  766.         Rect    screen = qd.screenBits.bounds;
  767.         
  768.         screen.top += GetMBarHeight();
  769.         
  770.         short    topSpace = screen.bottom - screen.top - r.bottom - r.top;
  771.         short    leftSpace = screen.right - screen.left - r.right - r.left;
  772.         
  773.         OffsetRect( &r, ( leftSpace / 2 ) - r.left, ( topSpace / 4 ) - r.top );
  774.         
  775.         // that's the one- do the animation
  776.             
  777.         ZoomRects( &gZoomFXSourceRect, &r, 10, kZoomAccelerate );
  778.         
  779.         // store the rects on behalf of the dialog/alert so we can do the reverse animation
  780.         // when we are reactivated
  781.         
  782.         fStoredZoomSource = gZoomFXSourceRect;
  783.         fStoredZoom = r;
  784.     }
  785.  
  786.     #endif
  787. }
  788.  
  789.  
  790. /*----------------------------------***  ACTIVATE  ***----------------------------------*/
  791. /*    
  792. the modal dialog is going away, so reactivate the floaters and top window
  793. ----------------------------------------------------------------------------------------*/
  794.  
  795. void    ZWindowManager::Activate()
  796. {
  797.     // a dialog is going away, so all floaters plus the top window must be reactivated
  798.     
  799.     SendMessage( kWMMsgMacDialogDown, NULL );
  800.     
  801.     ZWindow*    zw;
  802.     
  803.     if ( wmDDDeactivated )
  804.     {
  805.         zw = GetTopWindow();
  806.         
  807.         if ( zw )
  808.             PostActivation( zw, TRUE );
  809.             
  810.         wmDDDeactivated = FALSE;
  811.     }
  812.     
  813. #if _ALL_FLOATERS_ACTIVE == OFF
  814.     
  815.     zw = GetTopFloater();
  816.     
  817.     if ( zw )
  818.         PostActivation( zw, TRUE );
  819.  
  820. #else
  821.     
  822.     short    i;
  823.     
  824.     for (i = 1; i <= floaters->CountItems(); i++ )
  825.     {
  826.         zw = (ZWindow*) floaters->GetObject( i );
  827.     
  828.         if ( zw )
  829.             PostActivation( zw, TRUE );
  830.     }
  831.     
  832. #endif
  833.  
  834.     // if we have a stored zoom, zoom down from it.
  835.     
  836. #if _ZOOM_RECT_FX
  837.     
  838.     if ( ! EmptyRect( &fStoredZoom ) && gMacInfo.hasDragManager )
  839.     {
  840.         ZoomRects( &fStoredZoom, &fStoredZoomSource, 10, kZoomDecelerate );
  841.     
  842.         SetRect( &fStoredZoom, 0, 0, 0, 0 );
  843.         fStoredZoomSource = fStoredZoom;
  844.     }
  845.     
  846. #endif
  847.  
  848.     wmActive = TRUE;
  849. }
  850.  
  851.  
  852. /*--------------------------------***  GETTOPWINDOW  ***--------------------------------*/
  853. /*    
  854. get uppermost non-floating window
  855. ----------------------------------------------------------------------------------------*/
  856.  
  857. ZWindow*    ZWindowManager::GetTopWindow()
  858. {
  859.     // returns the top non-floating window
  860.     
  861.     if ( nonFloaters->CountItems() > 0 )
  862.         return (ZWindow*) nonFloaters->GetObject( 1 );
  863.     else
  864.         return NULL;
  865. }
  866.  
  867.  
  868. /*-------------------------------***  GETTOPFLOATER  ***--------------------------------*/
  869. /*    
  870. get uppermost floating window
  871. ----------------------------------------------------------------------------------------*/
  872.  
  873. ZWindow*    ZWindowManager::GetTopFloater()
  874. {
  875.     // returns the top floating window (even if not visible)
  876.     
  877.     if ( floaters->CountItems() > 0 )
  878.         return (ZWindow*) floaters->GetObject( 1 );
  879.     else
  880.         return NULL;
  881. }
  882.  
  883.  
  884. /*------------------------------***  GETBOTTOMFLOATER  ***------------------------------*/
  885. /*    
  886. get the last window in the floating layer. Top window is the one behind this.
  887. ----------------------------------------------------------------------------------------*/
  888.  
  889. ZWindow*    ZWindowManager::GetBottomFloater()
  890. {
  891.     // returns the bottom-most VISIBLE floater
  892.     
  893.     long    fCount = floaters->CountItems();
  894.     
  895.     if ( fCount > 0 )
  896.     {
  897.         ZWindow*    botFloater;
  898.         
  899.         // iterate through the list of floaters looking for the bottom-most visible one.
  900.         // Iterate in reverse order to facilitate finding the bottom one.
  901.         
  902.         while( fCount )
  903.         {
  904.             botFloater = (ZWindow*) floaters->GetObject( fCount-- );
  905.             
  906.             if ( botFloater->IsVisible())
  907.                 break;
  908.             else
  909.                 botFloater = NULL;
  910.         }
  911.         
  912.         return botFloater;    
  913.     }
  914.     else
  915.         return NULL;    
  916. }
  917.  
  918.  
  919. /*------------------------------***  MOVEWINDOWBEHIND  ***------------------------------*/
  920. /*    
  921. move <aWindow> behind <behindWindow>. If NULL, moves it behind all others. Works for
  922. floaters too, within their layer.
  923. ----------------------------------------------------------------------------------------*/
  924.  
  925. void        ZWindowManager::MoveWindowBehind( ZWindow* aWindow, ZWindow* behindWindow )
  926. {
  927.     FailNILParam( aWindow );
  928.     
  929.     long        wIndex, nIndex;
  930.     Boolean        wasActive = FALSE;
  931.     
  932.     if ( aWindow->Floats())
  933.     {
  934.         if ( behindWindow != NULL )
  935.         {
  936.             if ( ! behindWindow->Floats())
  937.                 behindWindow = GetBottomFloater();
  938.         }
  939.         else
  940.             behindWindow = GetBottomFloater();
  941.             
  942.         // manipulate our list
  943.         
  944.         wIndex = floaters->FindIndex( aWindow );
  945.         nIndex = floaters->FindIndex( behindWindow );
  946.         
  947.         floaters->MoveItem( wIndex, nIndex );
  948.     }
  949.     else
  950.     {
  951.         if ( behindWindow == NULL )
  952.             behindWindow = (ZWindow*) nonFloaters->GetObject( nonFloaters->CountItems());
  953.         
  954.         wasActive = aWindow->IsActive();
  955.         wIndex = nonFloaters->FindIndex( aWindow );
  956.         nIndex = nonFloaters->FindIndex( behindWindow );
  957.         
  958.         nonFloaters->MoveItem( wIndex, nIndex );
  959.     }    
  960.     
  961.     BringBehind( aWindow, behindWindow );
  962.     
  963.     if ( wasActive )
  964.     {
  965.         PostActivation( aWindow, FALSE );
  966.         SelectWindow( GetTopWindow());
  967.     }
  968. }
  969.  
  970.  
  971. /*------------------------------***  CHECKDIALOGEVENT  ***------------------------------*/
  972. /*    
  973. determine if the event is aimed at a dialog. This replaces the toolbox IsDialogEvent call
  974. such that it does not call FrontWindow().
  975. ----------------------------------------------------------------------------------------*/
  976.  
  977. Boolean        ZWindowManager::CheckDialogEvent( EventRecord* theEvent )
  978. {
  979.     // the event is for a dialog if the window kind explicitly passed with certain events is
  980.     // a dialog, or for other events, that the top window as we know it is a dialog.
  981.     
  982.     WindowPeek    w;
  983.     Boolean        result = FALSE;
  984.     ZWindow*    zw;
  985.     
  986.     // is this a window explicit event?
  987.     
  988.     if ( theEvent->what == updateEvt ||
  989.          theEvent->what == activateEvt )
  990.     {
  991.         // yes, so get the window and see if it's a dialog
  992.         
  993.         w = (WindowPeek) theEvent->message;
  994.     
  995.         result = ( w->windowKind == dialogKind );
  996.     }
  997.     else
  998.     {
  999.         // is the event a mouse down? If so we need to see if it was in the active dialog
  1000.         // window.
  1001.         
  1002.         if ( theEvent->what == mouseDown )
  1003.         {
  1004.             short    part = FindWindow( theEvent->where, (WindowPtr*) &w );
  1005.             
  1006.             zw = GetTopWindow();
  1007.             
  1008.             result = (    part == inContent &&
  1009.                         w->windowKind == dialogKind &&
  1010.                         zw &&
  1011.                         zw->GetMacWindow() == (WindowPtr) w );
  1012.         }
  1013.         else
  1014.         {
  1015.             zw = GetTopWindow();
  1016.             
  1017.             // we do our own checks but also call the toolbox IsDialogEvent, so that
  1018.             // ballon help in dialogs is correctly displayed. (Balloon help hooks into
  1019.             // this routine to provide dialog balloons).
  1020.             
  1021.             result = ( zw &&
  1022.                        ((WindowPeek) zw->GetMacWindow())->windowKind == dialogKind &&
  1023.                        ( theEvent->what == keyDown ||
  1024.                          theEvent->what == autoKey ||
  1025.                          IsDialogEvent( theEvent )));
  1026.         }
  1027.     }
  1028.     return result;    
  1029. }
  1030.  
  1031.  
  1032. /*--------------------------------***  LOCATEWINDOW  ***--------------------------------*/
  1033. /*    
  1034. find the window under the mouse, or NULL if none are
  1035. ----------------------------------------------------------------------------------------*/
  1036.  
  1037. ZWindow*    ZWindowManager::LocateWindow( const Point globalMouse )
  1038. {
  1039.     WindowPeek    w;
  1040.     ZWindow*    zw = NULL;
  1041.     
  1042.     w = ( WindowPeek ) FrontWindow();
  1043.     
  1044.     while ( w )
  1045.     {
  1046.         if ( PtInRgn( globalMouse, w->strucRgn ))
  1047.         {        
  1048.             zw = GetZWindow(( WindowPtr ) w );
  1049.             break;
  1050.         }
  1051.         
  1052.         w = w->nextWindow;
  1053.     }
  1054.     
  1055.     return zw;
  1056. }
  1057.  
  1058.  
  1059. /*--------------------------------***  GETNTHWINDOW  ***--------------------------------*/
  1060. /*    
  1061. return the window <n>, or NULL if bad index
  1062. ----------------------------------------------------------------------------------------*/
  1063.  
  1064. ZWindow*    ZWindowManager::GetNthWindow( const long n )
  1065. {
  1066.     ZWindow*    zw = NULL;
  1067.     
  1068.     try
  1069.     {
  1070.         zw = (ZWindow*) nonFloaters->GetObject( n );
  1071.     }
  1072.     catch( OSErr err )
  1073.     {
  1074.     }
  1075.     
  1076.     return zw;
  1077. }
  1078.  
  1079.  
  1080. /*--------------------------------***  GETNTHFLOATER  ***-------------------------------*/
  1081. /*    
  1082. return the floating window <n>, or NULL if bad index
  1083. ----------------------------------------------------------------------------------------*/
  1084.  
  1085. ZWindow*    ZWindowManager::GetNthFloater( const long n )
  1086. {
  1087.     ZWindow*    zw = NULL;
  1088.     
  1089.     try
  1090.     {
  1091.         zw = (ZWindow*) floaters->GetObject( n );
  1092.     }
  1093.     catch( OSErr err )
  1094.     {
  1095.     }
  1096.     
  1097.     return zw;
  1098. }
  1099.     
  1100.  
  1101. /*----------------------------------***  ISDIALOG  ***----------------------------------*/
  1102. /*    
  1103. is the window a modal dialog?
  1104. ----------------------------------------------------------------------------------------*/
  1105.  
  1106. Boolean        ZWindowManager::IsDialog( ZWindow* aWindow )
  1107. {
  1108.     // return TRUE if the window is a modal dialog (but not for modeless ones)
  1109.     
  1110.     if ( aWindow )
  1111.     {
  1112.         ZDialog*    zd = dynamic_cast<ZDialog*> ( aWindow );
  1113.         
  1114.         if (zd && zd->IsModal())
  1115.             return TRUE;
  1116.         else
  1117.             return FALSE;
  1118.     }
  1119.     else
  1120.         return FALSE;
  1121. }
  1122.  
  1123.  
  1124. /*--------------------------***  GETUNIQUEUNTITLEDNAME  ***-----------------------------*/
  1125. /*    
  1126. as part of the human interface guidelines adherence, we automatically name new windows
  1127. untitled, untitled 1, etc. This method scans through the names of all the windows in the
  1128. main list (ignores floaters), making sure the name is unique. If not, it appends 1, 2, etc
  1129. until the name is unique. If the name was unique, it returns FALSE, otherwise TRUE. i.e.
  1130. TRUE means we modified the name. Uses EqualString to compare names, ignores case.
  1131. ----------------------------------------------------------------------------------------*/
  1132.  
  1133. Boolean        ZWindowManager::GetUniqueUntitledName( Str255 wName )
  1134. {
  1135.     short        n = 1, i;
  1136.     Boolean        result = FALSE, match;
  1137.     Str255        sName, temp;
  1138.     ZWindow*    zw;
  1139.     
  1140.     CopyPString( wName, temp );
  1141.     
  1142.     do
  1143.     {
  1144.         match = FALSE;
  1145.         
  1146.         for ( i = 1; i <= nonFloaters->CountItems(); i++ )
  1147.         {    
  1148.             zw = (ZWindow*) nonFloaters->GetObject( i );
  1149.             zw->GetName( sName );
  1150.             
  1151.             if ( EqualString( temp, sName, FALSE, FALSE ))
  1152.             {
  1153.                 match = TRUE;
  1154.                 break;
  1155.             }
  1156.         }
  1157.         
  1158.         if ( match )
  1159.         {
  1160.             // the name matched some window, so append a digit and try again
  1161.         
  1162.             CopyPString( wName, temp );
  1163.             
  1164.             NumToString( n++, sName );
  1165.             ConcatPStrings( temp, "\p " );
  1166.             ConcatPStrings( temp, sName );
  1167.         }
  1168.         else
  1169.         {
  1170.             result = TRUE;
  1171.             CopyPString( temp, wName );
  1172.         }
  1173.     }
  1174.     while( ! result );
  1175.     
  1176.     return result;    
  1177. }
  1178.  
  1179.  
  1180. /*----------------------------------***  FLOATIDLE  ***---------------------------------*/
  1181. /*    
  1182. pass idle to each floater, in case they do periodic action
  1183. ----------------------------------------------------------------------------------------*/
  1184.  
  1185. void    ZWindowManager::FloatIdle()
  1186. {
  1187.     long        i;
  1188.     ZWindow*    aFloater;
  1189.     
  1190.     for( i = 1; i <= floaters->CountItems(); i++ )
  1191.     {
  1192.         aFloater = (ZWindow*) floaters->GetObject( i );
  1193.     
  1194.         if ( aFloater )
  1195.             aFloater->GetHandler()->Idle();
  1196.     }    
  1197. }
  1198.  
  1199.  
  1200. /*---------------------------------***  COUNTWINDOWS  ***-------------------------------*/
  1201. /*    
  1202. return the number of non-floating windows the manager knows about
  1203. ----------------------------------------------------------------------------------------*/
  1204.  
  1205. short        ZWindowManager::CountWindows()
  1206. {
  1207.     return nonFloaters->CountItems();
  1208. }
  1209.  
  1210. /*---------------------------------***  COUNTFLOATERS  ***------------------------------*/
  1211. /*    
  1212. return the number of floating windows the manager knows about
  1213. ----------------------------------------------------------------------------------------*/
  1214.  
  1215. short        ZWindowManager::CountFloaters()
  1216. {
  1217.     return floaters->CountItems();
  1218. }
  1219.  
  1220.  
  1221. /*--------------------------------***  SETWINDOWSMENU  ***------------------------------*/
  1222. /*    
  1223. sets the passed menu to be the application's "Windows" menu. Called by ZMenuBar- do not
  1224. call this method directly- use gMenuBar->NominateWindowsMenu() instead. This should be
  1225. called before any non-floating windows are created.
  1226. ----------------------------------------------------------------------------------------*/
  1227.  
  1228. void        ZWindowManager::SetWindowsMenu( MenuHandle aMenu )
  1229. {
  1230.     FailNILParam( aMenu );
  1231.     
  1232.     wmMenu = aMenu;
  1233.     wmItemOffset = CountMenuItems( aMenu );
  1234.     
  1235.     // make a list to keep an ordered list of windows that does not depend on
  1236.     // the front-to-back order
  1237.     
  1238.     FailNIL( wmWindows = new ZWindowList());
  1239.     
  1240.     BuildWindowsMenu();
  1241. }
  1242.  
  1243.  
  1244. /*-----------------------------***  SELECTWINDOWFROMMENU  ***---------------------------*/
  1245. /*    
  1246. called only by the main menubar to select the window from the menu. Do not call this
  1247. yourself.
  1248. ----------------------------------------------------------------------------------------*/
  1249.  
  1250. void        ZWindowManager::SelectWindowFromMenu( const short itemID )
  1251. {
  1252.     if ( wmMenu && wmWindows && !IsDialog( GetTopWindow()))
  1253.     {
  1254.         short    n = itemID - wmItemOffset;
  1255.         
  1256.         if ( wmItemOffset > 0 )
  1257.             n--;    // allow for divider line
  1258.         
  1259.         if (( n > 0 ) && ( n <= wmWindows->CountItems()))
  1260.         {
  1261.             ZWindow*    zw = (ZWindow*) wmWindows->GetObject( n );
  1262.         
  1263.             if ( zw )
  1264.                 zw->Select();
  1265.         }
  1266.     }
  1267. }
  1268.  
  1269.  
  1270. /*-------------------------------***  ZOOMWINDOWCLOSED  ***-----------------------------*/
  1271. /*
  1272. called when a window is closed to perform the "zoom closed" animation, if this effect
  1273. is enabled.    
  1274. ----------------------------------------------------------------------------------------*/
  1275.  
  1276. void        ZWindowManager::ZoomWindowClosed( ZWindow* aWindow )
  1277. {
  1278. #if _ZOOM_RECT_FX
  1279.  
  1280.     if ( gMacInfo.hasDragManager && ( gApplication->GetPhase() == kRunning ))
  1281.     {
  1282.         RgnHandle    wStruct;
  1283.         
  1284.         aWindow->GetStructureRegion( wStruct = NewRgn());
  1285.         
  1286.         ZoomRects( &(*wStruct)->rgnBBox, &aWindow->zoomSource, 10, kZoomDecelerate );
  1287.         DisposeRgn( wStruct );
  1288.     }
  1289.  
  1290. #endif
  1291. }
  1292.  
  1293.  
  1294. Boolean        ZWindowManager::CommandClickInFrontDragBar( ZWindow* target, const Point startPt )
  1295. {
  1296. #if _USE_DIR_POPUP
  1297.     
  1298.     // if we're using the directory pop-up code, call that here.
  1299.     // has the window got a file?
  1300.     
  1301.     FSSpec        ffs;
  1302.     Boolean        result;    
  1303.     
  1304.     target->GetFileSpec( &ffs );
  1305.     
  1306.     if ( ffs.vRefNum != kNoFile )
  1307.     {
  1308.         // we have a spec, so do that menu tracking thang, courtesy of Marco Piovanelli...
  1309.         
  1310.         result = TrackDirectoryPopup( &ffs, target->GetMacWindow(), startPt );
  1311.         
  1312.         if ( result )
  1313.         {
  1314.             // ffs now contains spec of selected directory, so we now assemble
  1315.             // an apple event to tell the Finder to open it.
  1316.             
  1317.             FailOSErr( OpenFinderObject( &ffs ));
  1318.         }
  1319.         else
  1320.             result = ! StillDown();
  1321.             
  1322.         return result;
  1323.     }
  1324.     else
  1325.         return FALSE;
  1326.  
  1327. #else
  1328.     return FALSE;
  1329. #endif
  1330. }
  1331.  
  1332.  
  1333. short        ZWindowManager::SaveWindowPosition( ZWindow* aWindow, ZResourceFile* aFile, short id )
  1334. {
  1335. #if _WPOS_WINDOW_PLACEMENT
  1336.  
  1337.     WPosHdl                wpH;
  1338.     ZResourceFile*        st;
  1339.     Rect                pr;
  1340.     short                x, y;
  1341.     
  1342.     FailNILParam( aWindow );
  1343.     
  1344.     // if <aFile> is NULL, use gPrefsFile if it exists. Otherwise do nothing.
  1345.     
  1346.     if ( aFile == NULL )
  1347.         st = (ZResourceFile*) gPrefsFile;
  1348.     else
  1349.         st = aFile;
  1350.         
  1351.     if ( st == NULL )
  1352.         return 0;
  1353.     
  1354.     FailNIL( wpH = ( WPosHdl ) NewHandleClear( sizeof( WPosResource )));
  1355.     
  1356.     aWindow->GetGlobalPosition( &x, &y );
  1357.     pr = aWindow->GetMacWindow()->portRect;
  1358.     
  1359.     (*wpH)->globalH = x;
  1360.     (*wpH)->globalV = y;
  1361.     (*wpH)->width = pr.right - pr.left;
  1362.     (*wpH)->height = pr.bottom - pr.top;
  1363.     
  1364.     if ( id == 0 )
  1365.         id = _UNIQUE_ID;
  1366.         
  1367.     // make sure the resource fork is open, etc. In general the file should already exist-
  1368.     // this will create it if not, but you'll have more control if you deal with this.
  1369.     
  1370.     if ( ! st->IsReal() || ! st->HasResFork())
  1371.         st->CreateResFork();
  1372.         
  1373.     short    rf = st->GetResourceRefNumber();
  1374.     
  1375.     try
  1376.     {    
  1377.         st->OpenResFork();
  1378.         st->WriteResource((Handle) wpH, kWindowPosResType, id );
  1379.         
  1380.         ReleaseResource((Handle) wpH );
  1381.         
  1382.         if ( rf == _NOT_OPEN )
  1383.             st->CloseResFork();
  1384.     }
  1385.     catch( OSErr err )
  1386.     {
  1387.         if ( rf == _NOT_OPEN )
  1388.             st->CloseResFork();
  1389.             
  1390.         // don't propagate- not important.
  1391.     }
  1392.     
  1393. #endif
  1394.  
  1395.     // return the ID we actually used: (TO DO)
  1396.     
  1397.     return 0;
  1398. }
  1399.  
  1400. void        ZWindowManager::RestoreWindowPosition( ZWindow* aWindow, ZResourceFile* aFile, const short id )
  1401. {
  1402. #if _WPOS_WINDOW_PLACEMENT
  1403.  
  1404.     WPosHdl                wpH;
  1405.     ZResourceFile*        st;
  1406.     Rect                pr;
  1407.  
  1408.     FailNILParam( aWindow );
  1409.     
  1410.     // if <aFile> is NULL, use gPrefsFile if it exists. Otherwise do nothing.
  1411.     
  1412.     if ( aFile == NULL )
  1413.         st = (ZResourceFile*) gPrefsFile;
  1414.     else
  1415.         st = aFile;
  1416.         
  1417.     if ( st == NULL )
  1418.         return;
  1419.     
  1420.     // detach & read the pos resource, if any.
  1421.     
  1422.     short     rf = st->GetResourceRefNumber();
  1423.     
  1424.     try
  1425.     {
  1426.         st->OpenResFork();    
  1427.         wpH = (WPosHdl) st->ReadResource( kWindowPosResType, id );
  1428.         
  1429.         if ( wpH )
  1430.         {    
  1431.             // build the potential global rect of the window, to see if it's going to be on screen.
  1432.             // Note that under System 8.0+, the window frame can be dragged by its edges, but on
  1433.             // earlier systems only the title bar is draggable. We must check that a DRAGGABLE part of
  1434.             // the window is visible before moving it to that location.
  1435.             
  1436.             SetRect( &pr, 0, 0, (*wpH)->width, (*wpH)->height );
  1437.             OffsetRect( &pr, (*wpH)->globalH, (*wpH)->globalV );
  1438.             
  1439.             short    tBar = aWindow->GetTitleBarHeight();
  1440.             
  1441.             pr.top -= tBar;
  1442.             
  1443.             // modify rect according to titlebar height, and system, etc
  1444.             
  1445.             if ( gMacInfo.systemVersion < 0x0800 )
  1446.                 pr.bottom = pr.top + tBar;
  1447.             
  1448.             // if on screen, move the window. Otherwise leave it where it is:
  1449.             
  1450.             if ( WindowOnDesktop( &pr ))
  1451.                 aWindow->PlaceAt((*wpH)->globalH, (*wpH)->globalV );
  1452.         
  1453.             ReleaseResource((Handle) wpH );
  1454.         }
  1455.  
  1456.         if ( rf == _NOT_OPEN )
  1457.             st->CloseResFork();
  1458.     }
  1459.     catch( OSErr err )
  1460.     {
  1461.         if ( rf == _NOT_OPEN )
  1462.             st->CloseResFork();
  1463.             
  1464.         // don't propagate- it's not serious if this fails.
  1465.     }
  1466.     
  1467. #endif
  1468. }
  1469.  
  1470.  
  1471.  
  1472. #pragma mark -
  1473.  
  1474. /*---------------------------------***  BRINGBEHIND  ***--------------------------------*/
  1475. /*    
  1476. change the window ordering so it is behind another. If behindWindow is NULL, window is
  1477. brought to the front.
  1478. ----------------------------------------------------------------------------------------*/
  1479.  
  1480. void        ZWindowManager::BringBehind( ZWindow* aWindow, ZWindow* behindWindow )
  1481. {
  1482.     // brings <aWindow> behind <behindWindow>. If <behindWindow> is NULL, it is brought
  1483.     // to the front. This manipulates the mac windowlist to match the state here.
  1484.     
  1485.     WindowPtr    a, b;
  1486.     
  1487.     if ( aWindow == behindWindow )
  1488.         return;
  1489.     
  1490.     if ( behindWindow )
  1491.     {
  1492.         a = aWindow->GetMacWindow();
  1493.         b = behindWindow->GetMacWindow();
  1494.         
  1495.         SendBehind( a, b );
  1496.     }
  1497.     else
  1498.         BringToFront( aWindow->GetMacWindow()); 
  1499. }
  1500.  
  1501.  
  1502. /*-------------------------------***  POSTACTIVATION  ***-------------------------------*/
  1503. /*    
  1504. simulate an activation event for the window
  1505. ----------------------------------------------------------------------------------------*/
  1506.  
  1507. void        ZWindowManager::PostActivation( ZWindow* aWindow, Boolean state )    
  1508. {
  1509.     // posts an activate event for the window. This will be picked up by the event handler, which
  1510.     // will then maintain the command chain correctly. Floater activations are never sent in this
  1511.     // way, but their activate methods are called directly.
  1512.     
  1513.     if ( aWindow->IsVisible())
  1514.     {
  1515.         HiliteWindow( aWindow->GetMacWindow(), state );
  1516.     
  1517.         if ( aWindow->Floats())
  1518.         {
  1519.             if ( state )
  1520.                 aWindow->Activate();
  1521.             else
  1522.                 aWindow->Deactivate();
  1523.         }
  1524.         else
  1525.         {
  1526.             
  1527.             #if _ACTIVATE_EVENTS_ARE_REAL
  1528.             
  1529.             EvQElPtr    evQ;
  1530.             
  1531.             if ( aWindow )
  1532.             {
  1533.                 long        evtMessage = (long) aWindow->GetMacWindow();
  1534.                 
  1535.                 FailOSErr( PPostEvent( activateEvt, evtMessage, &evQ ));
  1536.                 
  1537.                 // set up the modifiers to indicate activation state
  1538.                 
  1539.                 if ( state )
  1540.                     evQ->evtQModifiers |= activeFlag;
  1541.                 else
  1542.                     evQ->evtQModifiers &= ~activeFlag;
  1543.             }
  1544.             
  1545.             #else
  1546.  
  1547.             ZEventHandler*    ze = gApplication->GetEventHandler();
  1548.             
  1549.             ze->HandleWindowActivate( aWindow->GetMacWindow(), state );
  1550.             
  1551.             #endif
  1552.         
  1553.             SendMessage( state? kWMMsgWindowActivated : kWMMsgWindowDeactivated, aWindow );
  1554.         }
  1555.     }
  1556. }
  1557.  
  1558.  
  1559. /*------------------------------***  CALCWINDOWRGNS  ***-------------------------------*/
  1560. /*    
  1561. calculate the union of the window structure regions in front of the window. This is used
  1562. to build a clip region for window dragging.
  1563. ----------------------------------------------------------------------------------------*/
  1564.  
  1565. void    ZWindowManager::CalcWindowRgns( ZWindow* aWindow, RgnHandle aRgn )
  1566. {
  1567.     // sets <theRgn> to the union of all windows in front if <aWindow>, including floaters.
  1568.     // This is used to form the clip region for a window drag. Note- this doesn't check the
  1569.     // parameters for sanity.
  1570.     
  1571.     SetEmptyRgn( aRgn );
  1572.     
  1573.     // the simplest way to achieve this is to scan the real mac window list, since that
  1574.     // allows us to treat the window ordering simply without consideration of our separate
  1575.     // lists.
  1576.     
  1577.     WindowPeek    w = (WindowPeek) FrontWindow();
  1578.     
  1579.     while (w && w != (WindowPeek) aWindow->GetMacWindow())
  1580.     {
  1581.         UnionRgn( w->strucRgn, aRgn, aRgn );
  1582.     
  1583.         w = w->nextWindow;
  1584.     }
  1585. }
  1586.  
  1587.  
  1588. /*------------------------------***  SHOWHIDEFLOATER  ***-------------------------------*/
  1589. /*    
  1590. show or hide a floater by moving it offscreen.
  1591. ----------------------------------------------------------------------------------------*/
  1592.  
  1593. void    ZWindowManager::ShowHideFloater( ZWindow* aFloater, Boolean hide )
  1594. {
  1595.     FailNILParam( aFloater );
  1596.     
  1597.     short        dh = 10000;
  1598.     Point        wLoc;
  1599.     WindowPtr    w = aFloater->GetMacWindow();
  1600.     Rect        dtBounds  = (*GetGrayRgn())->rgnBBox;
  1601.     
  1602.     if (! hide)
  1603.         dh = -dh;
  1604.         
  1605.     wLoc = topLeft( w->portRect );
  1606.     
  1607.     aFloater->Focus();
  1608.     LocalToGlobal( &wLoc );
  1609.     
  1610.     // don't attempt to hide or show more than once- it doesn't work. To this end we check
  1611.     // that the window is not already positioned
  1612.     
  1613.     if (( hide && wLoc.h < dtBounds.right ) ||
  1614.         ( ! hide && wLoc.h > dtBounds.right ))
  1615.         MoveWindow( w, wLoc.h + dh, wLoc.v, FALSE );    
  1616. }
  1617.  
  1618.  
  1619. /*-----------------------------***  BUILDWINDOWSMENU  ***-------------------------------*/
  1620. /*    
  1621. fill menu with current list of windows, and check current one.
  1622. ----------------------------------------------------------------------------------------*/
  1623.  
  1624. void    ZWindowManager::BuildWindowsMenu()
  1625. {
  1626.     short    n, i, mi;
  1627.     
  1628.     if ( wmMenu )
  1629.     {
  1630.         // delete items beyond initial number
  1631.         
  1632.         n = CountMenuItems( wmMenu );
  1633.         
  1634.         while( n > wmItemOffset )
  1635.             DeleteMenuItem( wmMenu, n-- );
  1636.             
  1637.         // set menu to window titles. If the offset was >0, add a dividing line first
  1638.         
  1639.         if ( wmWindows )
  1640.         {    
  1641.             ZWindow*    zw;
  1642.             Str255        title;
  1643.             
  1644.             n = wmWindows->CountItems();
  1645.             
  1646.             if (( wmItemOffset > 0 ) && ( n > 0 ))
  1647.                 AppendMenu( wmMenu, "\p-" );
  1648.         
  1649.             for( i = 1; i <= n; i++ )
  1650.             {
  1651.                 mi = i + wmItemOffset;
  1652.                 
  1653.                 if ( wmItemOffset > 0 )
  1654.                     mi++;    // allow for extra divider line
  1655.                 
  1656.                 zw = (ZWindow*) wmWindows->GetObject( i );
  1657.                 
  1658.                 zw->GetName( title );
  1659.                 
  1660.                 AppendMenu( wmMenu, "\px(" );
  1661.                 SetMenuItemText( wmMenu, mi, title );
  1662.                 
  1663.             #if _ENUMERATE_WM_CMDS
  1664.                 
  1665.                 if ( i < 11 )
  1666.                     SetItemCmd( wmMenu, mi, i + 0x2F );
  1667.             
  1668.             #endif
  1669.                 
  1670.                 if ( ! IsDialog( GetTopWindow()))
  1671.                     EnableItem( wmMenu, mi );
  1672.                 
  1673.                 // if window is active, check that item
  1674.                 
  1675.                 if ( zw == GetTopWindow())
  1676.                     CheckItem( wmMenu, mi, TRUE );
  1677.             }
  1678.         }
  1679.     }
  1680. }
  1681.  
  1682.  
  1683. Boolean        ZWindowManager::WindowOnDesktop( Rect* wFrame )
  1684. {
  1685.     // return TRUE if the rect passed intersects the desktop. Called by RestoreWindowPosition
  1686.     // to see if the restored position is legal on this system.
  1687.     
  1688.     RectRgn( gUtilRgn, wFrame );
  1689.     SectRgn( gUtilRgn, GetGrayRgn(), gUtilRgn );
  1690.  
  1691.     return ( ! EmptyRgn( gUtilRgn ));
  1692. }
  1693.